]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
status/backlight: Add new quick toggle
authorFlorian Müllner <fmuellner@gnome.org>
Tue, 13 Jun 2023 19:36:20 +0000 (21:36 +0200)
committerMarge Bot <marge-bot@gnome.org>
Sun, 30 Jul 2023 11:12:50 +0000 (11:12 +0000)
Settings no longer exposes a slider for the keyboard brightness,
leaving keyboard shortcuts as the only way of adjusting it.

This is good enough in most cases, because devices with keyboard
backlight usually include corresponding keys on their keyboard.

However for devices without those keys, it would be good for the
settings to be exposed somewhere again. Quick settings seems like
a more appropriate place than "proper" Settings, since it gives
quick access that doesn't require a major focus change.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6765

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2820>

data/dbus-interfaces/org.gnome.SettingsDaemon.Power.Keyboard.xml [new file with mode: 0644]
data/gnome-shell-dbus-interfaces.gresource.xml
data/gnome-shell-icons.gresource.xml
data/icons/scalable/status/keyboard-brightness-high-symbolic.svg [new file with mode: 0644]
data/icons/scalable/status/keyboard-brightness-low-symbolic.svg [new file with mode: 0644]
data/icons/scalable/status/keyboard-brightness-medium-symbolic.svg [new file with mode: 0644]
data/theme/gnome-shell-sass/widgets/_quick-settings.scss
js/js-resources.gresource.xml
js/ui/panel.js
js/ui/status/backlight.js [new file with mode: 0644]
po/POTFILES.in

diff --git a/data/dbus-interfaces/org.gnome.SettingsDaemon.Power.Keyboard.xml b/data/dbus-interfaces/org.gnome.SettingsDaemon.Power.Keyboard.xml
new file mode 100644 (file)
index 0000000..75feb35
--- /dev/null
@@ -0,0 +1,7 @@
+<node>
+  <interface name='org.gnome.SettingsDaemon.Power.Keyboard'>
+    <property name='Brightness' type='i' access='readwrite'/>
+    <property name='Steps' type='i' access='read'/>
+  </interface>
+</node>
+
index 31d1f126661218c80feb12389bf56228ce97d0a2..c3954ba397f2c3390219d0d1b470a5d4598779e7 100644 (file)
@@ -37,6 +37,7 @@
     <file preprocess="xml-stripblanks">org.gnome.SessionManager.Presence.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.SessionManager.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Color.xml</file>
+    <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Power.Keyboard.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Power.Screen.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Rfkill.xml</file>
     <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file>
index a5dd1247bc2afe788568c211484a51a3350e084f..ceec3b89d71ccda028ac3b9f97c4e3295f3536f4 100644 (file)
@@ -22,6 +22,9 @@
     <file>scalable/actions/screenshot-ui-window-symbolic.svg</file>
     <file>scalable/actions/screenshot-recorded-symbolic.svg</file>
     <file>scalable/status/background-app-ghost-symbolic.svg</file>
+    <file>scalable/status/keyboard-brightness-high-symbolic.svg</file>
+    <file>scalable/status/keyboard-brightness-low-symbolic.svg</file>
+    <file>scalable/status/keyboard-brightness-medium-symbolic.svg</file>
     <file>scalable/status/keyboard-caps-lock-symbolic.svg</file>
     <file>scalable/status/keyboard-enter-symbolic.svg</file>
     <file>scalable/status/keyboard-hide-symbolic.svg</file>
diff --git a/data/icons/scalable/status/keyboard-brightness-high-symbolic.svg b/data/icons/scalable/status/keyboard-brightness-high-symbolic.svg
new file mode 100644 (file)
index 0000000..ca654a9
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+    <path d="m 8 3 c -0.554688 0 -1 0.445312 -1 1 v 1 c 0 0.554688 0.445312 1 1 1 s 1 -0.445312 1 -1 v -1 c 0 -0.554688 -0.445312 -1 -1 -1 z m -5 2.050781 c -0.238281 0.007813 -0.476562 0.105469 -0.660156 0.292969 c -0.390625 0.390625 -0.390625 1.019531 0 1.414062 l 0.71875 0.71875 c 0.390625 0.390626 1.023437 0.390626 1.414062 0 c 0.390625 -0.394531 0.390625 -1.023437 0 -1.414062 l -0.71875 -0.71875 c -0.207031 -0.210938 -0.484375 -0.308594 -0.753906 -0.292969 z m 9.949219 0 c -0.253907 0 -0.511719 0.097657 -0.707031 0.292969 l -0.71875 0.71875 c -0.390626 0.390625 -0.390626 1.023438 0 1.414062 c 0.390624 0.390626 1.023437 0.390626 1.414062 0 l 0.71875 -0.71875 c 0.390625 -0.390624 0.390625 -1.023437 0 -1.414062 c -0.195312 -0.195312 -0.453125 -0.292969 -0.707031 -0.292969 z m -11.949219 4.949219 c -0.554688 0 -1 0.445312 -1 1 s 0.445312 1 1 1 h 0.972656 c 0.554688 0 1 -0.445312 1 -1 s -0.445312 -1 -1 -1 z m 12.980469 0 c -0.550781 0 -1 0.445312 -1 1 s 0.449219 1 1 1 h 1.019531 c 0.554688 0 1 -0.445312 1 -1 s -0.445312 -1 -1 -1 z m 0 0"/>
+    <path d="m 5.5 10 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1.5 h 6 v -1.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -0.5 s -1.332031 0 -2 0 s -2 0 -2 0 z m 0 0"/>
+</svg>
diff --git a/data/icons/scalable/status/keyboard-brightness-low-symbolic.svg b/data/icons/scalable/status/keyboard-brightness-low-symbolic.svg
new file mode 100644 (file)
index 0000000..15a86c9
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+    <path d="m 8 4 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m -4.398438 1.601562 c -0.554687 0 -1 0.445313 -1 1 c 0 0.550782 0.445313 1 1 1 c 0.550782 0 1 -0.449218 1 -1 c 0 -0.554687 -0.449218 -1 -1 -1 z m 9 0 c -0.554687 0 -1 0.445313 -1 1 c 0 0.550782 0.445313 1 1 1 c 0.550782 0 1 -0.449218 1 -1 c 0 -0.554687 -0.449218 -1 -1 -1 z m -10.601562 4.398438 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 12 0 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0" fill-opacity="0.34902"/>
+    <path d="m 5.5 10 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1.5 h 6 v -1.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -0.5 s -1.332031 0 -2 0 s -2 0 -2 0 z m 0 0"/>
+</svg>
diff --git a/data/icons/scalable/status/keyboard-brightness-medium-symbolic.svg b/data/icons/scalable/status/keyboard-brightness-medium-symbolic.svg
new file mode 100644 (file)
index 0000000..bb51f14
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
+    <path d="m 8 4 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m -4.398438 1.601562 c -0.554687 0 -1 0.445313 -1 1 c 0 0.550782 0.445313 1 1 1 c 0.550782 0 1 -0.449218 1 -1 c 0 -0.554687 -0.449218 -1 -1 -1 z m 9 0 c -0.554687 0 -1 0.445313 -1 1 c 0 0.550782 0.445313 1 1 1 c 0.550782 0 1 -0.449218 1 -1 c 0 -0.554687 -0.449218 -1 -1 -1 z m -10.601562 4.398438 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 12 0 c -0.550781 0 -1 0.449219 -1 1 s 0.449219 1 1 1 s 1 -0.449219 1 -1 s -0.449219 -1 -1 -1 z m 0 0"/>
+    <path d="m 5.5 10 c -0.277344 0 -0.5 0.222656 -0.5 0.5 v 1.5 h 6 v -1.5 c 0 -0.277344 -0.222656 -0.5 -0.5 -0.5 h -0.5 s -1.332031 0 -2 0 s -2 0 -2 0 z m 0 0"/>
+</svg>
index 88d938409e5c7d8445f8f9e5ac83f1b811e6b530..870dba47d1cd36916d18c1f8bb94b5cd733fa54e 100644 (file)
 
 .device-subtitle { color: transparentize($fg_color, 0.5); }
 
+.keyboard-brightness-item .slider {
+  min-height: 16px;
+}
+
+.keyboard-brightness-level {
+  spacing: $base_padding;
+
+  .button:checked { @include button(default, $c:$selected_bg_color); }
+}
+
 // background apps
 
 .background-apps-quick-toggle {
index 1e36ed4a18bd5b8f6245048ecc07fc9292b3781c..e72cd31e12df975b8163170d7f523404a4067a9d 100644 (file)
     <file>ui/status/accessibility.js</file>
     <file>ui/status/autoRotate.js</file>
     <file>ui/status/backgroundApps.js</file>
+    <file>ui/status/backlight.js</file>
     <file>ui/status/brightness.js</file>
     <file>ui/status/camera.js</file>
     <file>ui/status/darkMode.js</file>
index b44635f56b77f45675f371b6354251380c414ae3..3a99c9e52764b9364e59c6ad57f350177b9987ec 100644 (file)
@@ -30,6 +30,7 @@ const SystemStatus = imports.ui.status.system;
 const LocationStatus = imports.ui.status.location;
 const NightLightStatus = imports.ui.status.nightLight;
 const DarkModeStatus = imports.ui.status.darkMode;
+const BacklightStatus = imports.ui.status.backlight;
 const ThunderboltStatus = imports.ui.status.thunderbolt;
 const AutoRotateStatus = imports.ui.status.autoRotate;
 const BackgroundAppsStatus = imports.ui.status.backgroundApps;
@@ -398,6 +399,7 @@ class QuickSettings extends PanelMenu.Button {
         this._thunderbolt = new ThunderboltStatus.Indicator();
         this._nightLight = new NightLightStatus.Indicator();
         this._darkMode = new DarkModeStatus.Indicator();
+        this._backlight = new BacklightStatus.Indicator();
         this._powerProfiles = new PowerProfileStatus.Indicator();
         this._rfkill = new RFKillStatus.Indicator();
         this._autoRotate = new AutoRotateStatus.Indicator();
@@ -414,6 +416,7 @@ class QuickSettings extends PanelMenu.Button {
         if (this._network)
             this._indicators.add_child(this._network);
         this._indicators.add_child(this._darkMode);
+        this._indicators.add_child(this._backlight);
         this._indicators.add_child(this._powerProfiles);
         if (this._bluetooth)
             this._indicators.add_child(this._bluetooth);
@@ -439,6 +442,7 @@ class QuickSettings extends PanelMenu.Button {
         this._addItems(this._powerProfiles.quickSettingsItems);
         this._addItems(this._nightLight.quickSettingsItems);
         this._addItems(this._darkMode.quickSettingsItems);
+        this._addItems(this._backlight.quickSettingsItems);
         this._addItems(this._rfkill.quickSettingsItems);
         this._addItems(this._autoRotate.quickSettingsItems);
         this._addItems(this._unsafeMode.quickSettingsItems);
diff --git a/js/ui/status/backlight.js b/js/ui/status/backlight.js
new file mode 100644 (file)
index 0000000..cb2904e
--- /dev/null
@@ -0,0 +1,205 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+/* exported Indicator */
+
+const {Clutter, Gio, GObject, St} = imports.gi;
+
+const {QuickMenuToggle, SystemIndicator} = imports.ui.quickSettings;
+
+const PopupMenu = imports.ui.popupMenu;
+const {Slider} = imports.ui.slider;
+
+const {loadInterfaceXML} = imports.misc.fileUtils;
+
+const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
+const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
+
+const BrightnessInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Power.Keyboard');
+const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);
+
+const SliderItem = GObject.registerClass({
+    Properties: {
+        'value': GObject.ParamSpec.int(
+            'value', '', '',
+            GObject.ParamFlags.READWRITE,
+            0, 100, 0),
+    },
+}, class SliderItem extends PopupMenu.PopupBaseMenuItem {
+    constructor() {
+        super({
+            activate: false,
+            style_class: 'keyboard-brightness-item',
+        });
+
+        this._slider = new Slider(0);
+
+        this._sliderChangedId = this._slider.connect('notify::value',
+            () => this.notify('value'));
+        this._slider.accessible_name = _('Keyboard Brightness');
+
+        this.add_child(this._slider);
+    }
+
+    get value() {
+        return this._slider.value * 100;
+    }
+
+    set value(value) {
+        this._slider.block_signal_handler(this._sliderChangedId);
+        this._slider.value = value / 100;
+        this._slider.unblock_signal_handler(this._sliderChangedId);
+    }
+});
+
+const DiscreteItem = GObject.registerClass({
+    Properties: {
+        'value': GObject.ParamSpec.int(
+            'value', '', '',
+            GObject.ParamFlags.READWRITE,
+            0, 100, 0),
+        'n-levels': GObject.ParamSpec.int(
+            'n-levels', '', '',
+            GObject.ParamFlags.READWRITE,
+            1, 3, 1),
+    },
+}, class DiscreteItem extends St.BoxLayout {
+    constructor() {
+        super({
+            style_class: 'popup-menu-item',
+            reactive: true,
+        });
+
+        this._levelButtons = new Map();
+        this._addLevelButton('off', _('Off'), 'keyboard-brightness-low-symbolic');
+        this._addLevelButton('low', _('Low'), 'keyboard-brightness-medium-symbolic');
+        this._addLevelButton('high', _('High'), 'keyboard-brightness-high-symbolic');
+
+        this.connect('notify::n-levels', () => this._syncLevels());
+        this.connect('notify::value', () => this._syncChecked());
+        this._syncLevels();
+    }
+
+    _valueToLevel(value) {
+        const checkedIndex = Math.round(value * (this.nLevels - 1) / 100);
+        if (checkedIndex === this.nLevels - 1)
+            return 'high';
+
+        return [...this._levelButtons.keys()].at(checkedIndex);
+    }
+
+    _levelToValue(level) {
+        const keyIndex = [...this._levelButtons.keys()].indexOf(level);
+        return 100 * Math.min(keyIndex, this.nLevels - 1) / (this.nLevels - 1);
+    }
+
+    _addLevelButton(key, label, iconName) {
+        const box = new St.BoxLayout({
+            style_class: 'keyboard-brightness-level',
+            vertical: true,
+            x_expand: true,
+        });
+
+        box.button = new St.Button({
+            styleClass: 'icon-button',
+            canFocus: true,
+            iconName,
+        });
+        box.add_child(box.button);
+
+        box.button.connect('clicked', () => {
+            this.value = this._levelToValue(key);
+        });
+
+        box.add_child(new St.Label({
+            text: label,
+            x_align: Clutter.ActorAlign.CENTER,
+        }));
+
+        this.add_child(box);
+        this._levelButtons.set(key, box);
+    }
+
+    _syncLevels() {
+        this._levelButtons.get('off').visible = this.nLevels > 0;
+        this._levelButtons.get('high').visible = this.nLevels > 1;
+        this._levelButtons.get('low').visible = this.nLevels > 2;
+    }
+
+    _syncChecked() {
+        const checkedKey = this._valueToLevel(this.value);
+        this._levelButtons.forEach((b, k) => {
+            b.button.checked = k === checkedKey;
+        });
+    }
+});
+
+const KeyboardBrightnessToggle = GObject.registerClass(
+class KeyboardBrightnessToggle extends QuickMenuToggle {
+    _init() {
+        super._init({
+            title: _('Keyboard'),
+            iconName: 'display-brightness-symbolic',
+        });
+
+        this._proxy = new BrightnessProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
+            (proxy, error) => {
+                if (error)
+                    console.error(error.message);
+                else
+                    this._proxy.connect('g-properties-changed', () => this._sync());
+                this._sync();
+            });
+
+        this.connect('clicked', () => {
+            this._proxy.Brightness = this.checked ? 0 : 100;
+        });
+
+        this._sliderItem = new SliderItem();
+        this.menu.box.add_child(this._sliderItem);
+
+        this._discreteItem = new DiscreteItem();
+        this.menu.box.add_child(this._discreteItem);
+
+        this._sliderItem.bind_property('visible',
+            this._discreteItem, 'visible',
+            GObject.BindingFlags.INVERT_BOOLEAN |
+            GObject.BindingFlags.SYNC_CREATE);
+
+        this._sliderItem.bind_property('value',
+            this._discreteItem, 'value',
+            GObject.BindingFlags.SYNC_CREATE);
+
+        this._sliderItem.connect('notify::value',
+            () => (this._proxy.Brightness = this._sliderItem.value));
+
+        this._discreteItem.connect('notify::value',
+            () => (this._proxy.Brightness = this._discreteItem.value));
+    }
+
+    _sync() {
+        const brightness = this._proxy.Brightness;
+        const visible = Number.isInteger(brightness) && brightness >= 0;
+        this.visible = visible;
+        if (!visible)
+            return;
+
+        this.checked = brightness > 0;
+        const useSlider = this._proxy.Steps >= 4;
+
+        this._sliderItem.set({
+            visible: useSlider,
+            value: brightness,
+        });
+
+        if (!useSlider)
+            this._discreteItem.nLevels = this._proxy.Steps;
+    }
+});
+
+var Indicator = GObject.registerClass(
+class Indicator extends SystemIndicator {
+    _init() {
+        super._init();
+
+        this.quickSettingsItems.push(new KeyboardBrightnessToggle());
+    }
+});
index 098142518002f5424dcbe8ba31076be325901586..74a521202207a023c593bb9f90c46bdb8b10e711 100644 (file)
@@ -60,6 +60,7 @@ js/ui/shellMountOperation.js
 js/ui/status/accessibility.js
 js/ui/status/autoRotate.js
 js/ui/status/backgroundApps.js
+js/ui/status/backlight.js
 js/ui/status/bluetooth.js
 js/ui/status/brightness.js
 js/ui/status/darkMode.js